﻿Tennis tournament
Потребно е да направите сценарио за синхронизација на турнир во тенис за двојки.

На турнирот се натпреваруваат зелена со црвена група, каде во секоја од групите има по 30 учесници.

Потребно е да го синхронизирате турнирот на следниот начин:

По стартувањето на играчите во позадина, тие најпрво треба да испечатат {Red|Green} player ready
На теренот може да влезат по 2 играчи од двете групи. По влегувањето треба да испечатат {Red|Geen} player enters field
Доколку влезат повеќе од 2 играчи од некоја од групте, сценариото е невалидно
Откако ќе влезат четирите играчи на теренот, треба истовремено да започнат со играта со печатење на Match started и повикување на Thread.sleep(200)
Треба да се повика истовремено и паралелно да се повика кај сите играчи.
Откако ќе заврши Thread.sleep кај сите играчи сите печатат {Red|Green} player finished playing
Потоа само еден играч печати Match finished и сигнализира дека теренот е слободен.
Потребно е да имплементирате сценарио во кое во main методот ќе се стартуваат по 30 инстанци од класите Greenplayer и Redplayer кои ќе се однесуваат како Threads и во позадина секоја ќе знае да изигра една партија според претходно опишаното сценарио. Откако сите играчи ќе се стартуваат, треба за секој од нив да се почека да заврши за максимум 1 секунда (1000 ms). Потоа треба да се провери дали сите инстанци се завршени со позадинското извршување. Доколку некоја инстанца не е завршена, потребно е истата да се терминира и да се испечати пораката: Possible deadlock.

Имплементацијата на сценариото треба да се направи во execute методите, кои треба да се стартуваат во позадина.


import java.util.HashSet;
import java.util.concurrent.Semaphore;

public class TennisTournament {


    static int greenNum = 0;
    static Semaphore lock = new Semaphore(1);

    static Semaphore red = new Semaphore(2);
    static Semaphore green = new Semaphore(2);

    static Semaphore redHere = new Semaphore(0);
    static Semaphore ready = new Semaphore(0);

    static Semaphore done = new Semaphore(0);


    public static class GreenPlayer extends Thread {

        @Override
        public void run() {
            try {
                execute();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public void execute() throws InterruptedException {
            System.out.println("Green player ready");
            green.acquire();
            System.out.println("Green player enters field");
            lock.acquire();
            greenNum++;
            if (greenNum == 2) {
                lock.release();
                redHere.acquire(2);
                ready.release(4);
            } else {
                lock.release();
            }
            ready.acquire();
            System.out.println("Match started");
            Thread.sleep(200);
            System.out.println("Green player finished playing");
            done.release();

            lock.acquire();
            greenNum--;
            if (greenNum == 0) {

                done.acquire(4);
                // TODO: only one player calls the next line per match
                System.out.println("Match finished");
                green.release(2);
                red.release(2);
            }
            lock.release();
        }

    }

    public static class RedPlayer extends Thread {

        @Override
        public void run() {
            try {
                execute();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public void execute() throws InterruptedException {
            System.out.println("Red player ready");
            red.acquire();
            System.out.println("Red player enters field");
            redHere.release();
            ready.acquire();
            System.out.println("Match started");
            Thread.sleep(200);
            System.out.println("Red player finished playing");
            done.release();
        }

    }

    public static void main(String[] args) throws InterruptedException {
        // start 30 red and 30 green players in background
        HashSet<Thread> threads = new HashSet<Thread>();
        for (int i = 0; i < 30; i++) {
            RedPlayer red = new RedPlayer();
            threads.add(red);
            GreenPlayer green = new GreenPlayer();
            threads.add(green);
        }
        for (Thread t : threads) {
            t.start();
        }
        // after all of them are started, wait each of them to finish for 1_000 ms
        for (Thread t : threads) {
            t.join(2_000);
        }
        // after the waiting for each of the players is done, check the one that are not finished and terminate them
        for (Thread t : threads) {
            if (t.isAlive()) {
                t.interrupt();
                System.err.println("POSSIBLE DEADLOCK!");
            }
        }

    }

}